/*
 * Copyright 2014 by État de Genève (Switzerland)
 * All rights reserved.
 *
 * Author: ELCA Informatique SA
 */
define([
    'services/layout',
    'i18n',
    'services/appConfig',
    'plugins/router',
    'services/notifier',
    'common/breadcrumb'],
    function (L, i18n, appConfig, router, notifier, breadcrumb) {

        var baseForm = function () {
            // will be overriden by the child's itemRef
            this.itemRef = { id: null, type: null };

            this.isInEditMode = ko.observable(false);
            // array containing all errors on form,
            // usually in objects with format: { path: ..., message: ... }
            this.formErrors = ko.observableArray();
            // get only messages (without paths)
            this.formErrorsMessages = ko.computed(getErrorMessages, this);

            // list of countries for select boxes
            this.countriesOptions = appConfig.getValues('pays');
            this.politesseOptions = appConfig.getValues('politesses');
            this.etatCivilsOptions = appConfig.getValues('etatCivils');
        };

        // allows scrolling to a specific section in the form
        baseForm.prototype.scrollTo = scrollTo;
        baseForm.prototype.compositionComplete = viewCompositionComplete;
        // basic action to load a new detail form use on link clicks
        baseForm.prototype.openDetail = openDetail;
        // allow passing a reference of the parent detailFormSelector that could be used to change this form
        // when a link is clicked
        baseForm.prototype.setFormSelector = setFormSelector;

        return baseForm;

        /**
         * get messages part of the the errorMessage array.
         * If no message is present but errors are present, returns a generic error message
         */
        function getErrorMessages() {

            var defaultMessage = i18n.t('cms:detailForm.defaultInvalidMsg');

            if(this.formErrors().length === 0) {
                return [];
            }

            function msgFilter(item) {
                if (item && item.message) {
                    return item.message;
                }
                return null;
            }

            var messages = null;
            if (this.formErrors().length > 0) {
                // foreach formErrors, retrieve the message part, delete empty or falsy entries, and ensure unicity of messages
                messages = _.uniq(_.compact(_.map(this.formErrors(), msgFilter)));
            }

            if (!messages || messages.length === 0) {
                return [defaultMessage];
            } else {
                return messages;
            }
        }

        function viewCompositionComplete(view) {
            L.needsRelayout();

            // this.title can be either a computed or a simple property
            breadcrumb.addDetailCrumb(this.itemRef, ko.unwrap(this.title), window.location.href);

            // use this for scroll spy
            //$(view).find('[data-spy="scroll"]').scrollspy('refresh');
        }

        /**
         * allows left menu to make the content scoll in the form
         */
        function scrollTo(elementId) {
            $('.op-detail-form').nanoScroller({ scrollTo: $('#' + elementId) });
        }

        /**
         * setup a reference to the formSelector that created this form instance
         */
        function setFormSelector(formSelector) {
            this.formSelector = formSelector;
        }

        /**
         * try to open the given dto in its form. the form can be different so a call to the parent formSelector
         * is necessary.
         * Also updates the router when applicable
         */
        function openDetail(linkDto) {
            var target = ko.mapping.toJS(linkDto);
            if(!target) {
                notifier.log(i18n.t('cms:error.invalidLink'));
                return;
            }

            // if we're in a 'list' route, replace or add entity type and id in route
            // else, navigate to the detail as is!
            var routeConf = router.activeInstruction().config;
            var newRoute = '#';
            if(routeConf.moduleId === 'lists/listTemplate') {

                // take the list part of the fragment, add new type and id, then querystring if any
                var currentList = router.activeInstruction().fragment.match('^([^/]+/[^/]+/[^/]+)')[0];
                var qs = router.activeInstruction().queryString;

                newRoute = currentList + '/' + target.type + '/' + target.id + (qs ? '?' + qs : '');
            } else {
                newRoute = 'detail/' + target.type + '/' + target.id;
            }

            if(this.formSelector) {
                this.formSelector.changeCurrentForm(target);
                router.navigate(newRoute, false);
            } else {
                router.navigate(newRoute);
            }

        }
    });